Skip to content

Allow cross-dataset-authored quizzes and lessons to sync#14765

Draft
rtibbles wants to merge 2 commits into
learningequality:developfrom
rtibbles:fix-sync-cross-dataset-authoring-fields
Draft

Allow cross-dataset-authored quizzes and lessons to sync#14765
rtibbles wants to merge 2 commits into
learningequality:developfrom
rtibbles:fix-sync-cross-dataset-authoring-fields

Conversation

@rtibbles
Copy link
Copy Markdown
Member

Summary

  • Quizzes/lessons authored by a cross-dataset superuser (e.g. a device's own super admin) fail to sync onto other devices: pre_save nulls the author FK, but it's blank=False, so deserialization rejects the null and the record stays dirty.
  • Fix: author FKs → blank=True, and skip pre_save enforcement during deserialization.
  • Refactor: consolidate the duplicated author-field logic (exam, lesson, attendance, course models) into AbstractFacilityDataModel.enforce_authoring_user_field. Fixes the same latent gap in AttendanceSession.

References

Reviewer guidance

  • Verify: as a super admin whose own facility differs from the content's, create a quiz/lesson, full-sync to a second device, confirm it appears there.
  • Caveat: exams/lessons/attendance now require a non-null author on every save, not just creation — so a null author can only ever come from sync, never from app code. (A record already stored with a null author can't be re-saved via the app.)

AI usage

  • Claude Code (Opus 4.7) investigated the bug from the Windows and Ubuntu device databases @radinamatic shared, then wrote the fix, regression test and refactor; I directed and reviewed throughout — pushing back on the initial blank-vs-null reasoning (verified against Django's validation path) and confirming the consolidation preserved the pre_save semantics from Align course model pre_save logic with awareness of deserialization #14130.

Move the repeated "require an author FK, allow null only during
deserialization, and drop references to a cross-dataset superuser" logic
out of the course models and into
AbstractFacilityDataModel.enforce_authoring_user_field, routing
CourseSession, CourseSessionAssignment and UnitTestAssignment through it.

No behaviour change: enforcement still happens on every non-deserialization
save, matching the semantics established in learningequality#14130.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added DEV: backend Python, databases, networking, filesystem... SIZE: medium labels May 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

Exam, Lesson and their assignments declared their author foreign key
null=True but blank=False, and required a creator in pre_save on add. When
a record authored by a superuser from a different dataset (whose author FK
is nulled by pre_save) was deserialized on a receiving device, clean_fields
rejected the null (blank=False) and the pre_save add-check fired, leaving
the record dirty in the Store and absent from the device.

Make the author foreign keys blank=True and route the pre_save checks
through enforce_authoring_user_field, which permits a null author during
deserialization. The helper gates the required-author check on _state.adding
so it fires only on local creation: a record that synced in with a null
author (its cross-dataset superuser dropped) is then editable locally rather
than raising IntegrityError on every PATCH. AttendanceSession had the same
pre_save gap and is fixed too.

Adds a serialize/deserialize regression test covering all three, a pre_save
test that a null author survives a later update, and a lesson API test for
PATCH of a null-created_by lesson.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rtibbles rtibbles force-pushed the fix-sync-cross-dataset-authoring-fields branch from 91ca5b3 to 62bbf33 Compare May 27, 2026 23:21
@radinamatic
Copy link
Copy Markdown
Member

No issues anymore in case of the device super admin user creation of lessons and quizzes on a second facility of their device: said facility can be imported on another device, lessons, quizzes and learners' progress fully visible there, and any updates on each of the devices is correctly displayed on the other upon facility sync! 🎉

Pre sync Post sync
Desktop Icons 2_019 Desktop Icons 2_021

Copy link
Copy Markdown
Member

@radinamatic radinamatic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 💯 :shipit: 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DEV: backend Python, databases, networking, filesystem... SIZE: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants